TITLE 01/03/84 TEST2 POWER ON SELF TEST
PUBLIC	C21
PUBLIC	SHUT2
PUBLIC	SHUT3
PUBLIC	SHUT4
PUBLIC	SHUT6
PUBLIC	SHUT7
PUBLIC	POST2

.XLIST
INCLUDE DSEG.SRC
INCLUDE POSTEQU.SRC
INCLUDE SYSDATA.INC
INCLUDE IAPX286.MAC
.LIST
INCLUDE SEGMENT.SRC

EXTRN	H5:NEAR
EXTRN	POST7:NEAR
EXTRN	SET_TOD:NEAR
EXTRN	E0:NEAR 			; 101 ERROR CODE
EXTRN	E0_A:NEAR			; 102 ERROR CODE
EXTRN	E0_B:NEAR			; 103 ERROR CODE

EXTRN	VIR_ERR:NEAR			; 104 ERROR CODE
EXTRN	CM4:NEAR			; 105 ERROR CODE
EXTRN	CM4_A:NEAR			; 106 ERROR CODE
EXTRN	CM4_B:NEAR			; 107 ERROR CODE
EXTRN	CM4_C:NEAR			; 108 ERROR CODE
EXTRN	CM4_D:NEAR			; 109 ERROR CODE
EXTRN	CM1:NEAR			; 161 ERROR CODE
EXTRN	CM2:NEAR			; 162 ERROR CODE
EXTRN	CM3:NEAR			; 163 ERROR CODE
EXTRN	E1_A:NEAR			; 164 ERROR CODE

EXTRN	E1:NEAR 			; 201 ERROR CODE
EXTRN	ADERR1:NEAR			; 202 ERROR CODE
EXTRN	ADERR:NEAR			; 203 ERROR CODE


EXTRN	F1:NEAR 			; 301 ERROR CODE
EXTRN	LOCK:NEAR			; 302 ERROR CODE
EXTRN	F1_A:NEAR			; 303 ERROR CODE
EXTRN	F1_B:NEAR			; 304 ERROR CODE

EXTRN	E1_B:NEAR			; 401 ERROR CODE
EXTRN	E1_C:NEAR			; 501 ERROR CODE

EXTRN	F3:NEAR 			; 601 ERROR CODE

EXTRN	KBD_RESET:NEAR
EXTRN	GATE_A20:NEAR

EXTRN	E_MSG:NEAR
EXTRN	XPC_BYTE:NEAR
EXTRN	VECTOR_TABLE:NEAR
EXTRN	SLAVE_VECTOR_TABLE:NEAR
EXTRN	NMI_INT:NEAR
EXTRN	PRINT_SCREEN:NEAR
EXTRN	BLINK_INT:NEAR
EXTRN	PRT_HEX:NEAR
EXTRN	F3B:NEAR
EXTRN	PRT_SEG:NEAR
EXTRN	XPC_BYTE:NEAR

EXTRN	ROM_CHECK:NEAR
EXTRN	ROS_CHECKSUM:NEAR
EXTRN	SEEK:NEAR
EXTRN	ERR_BEEP:NEAR
EXTRN	P_MSG:NEAR
EXTRN	START_1:NEAR
EXTRN	F4:NEAR
EXTRN	F4E:NEAR
EXTRN	F3A:NEAR
EXTRN	DISK_BASE:NEAR
EXTRN	F3D:NEAR
EXTRN	F3D1:NEAR
EXTRN	PROC_SHUTDOWN:NEAR
EXTRN	SYSINIT1:NEAR
EXTRN	PROT_PRT_HEX:NEAR
EXTRN	DISK_IO:NEAR
EXTRN	HD_INT:NEAR
EXTRN	C8042:NEAR
EXTRN	OBF_42:NEAR
EXTRN	STGTST_CNT:NEAR
EXTRN	BOOT_STRAP_1:NEAR
EXTRN	XMIT_8042:NEAR
EXTRN	ROM_ERR:NEAR
EXTRN	DDS:NEAR
EXTRN	DISK_SETUP:NEAR
EXTRN	DSKETTE_SETUP:NEAR
;--------------------------------------------------------
; TEST.17						:
;	8259 INTERRUPT CONTROLLER TEST			:
; DESCRIPTION						:
;	READ/WRITE THE INTERRUPT MASK REGISTER (IMR)	:
;	WITH ALL ONES AND ZEROES, ENABLE SYSTEM 	:
;	INTERRUPTS,  MASK DEVICE INTERRUPTS OFF. CHECK	:
;	FOR HOT INTERRUPTS (UNEXPECTED).		:
;--------------------------------------------------------

	ASSUME	CS:CODE
	ASSUME	DS:DATA

POST2	PROC	NEAR

C21:	MOV	AL,10			; LINE FEED ON CRT
	CALL	PRT_HEX 		;
	CALL	DDS			;SET DATA SEGMENT

;----- TEST THE IMR REGISTERS

C21A:	CLI				; TURN OFF INTERRUPTS
	MOV	AL,0			; SET IMR TO ZERO
	OUT	INTA01,AL
	OUT	INTB01,AL		; SEND TO 2ND INT
	JMP	SHORT $+2		;
	IN	AL,INTA01		; READ IMR
	MOV	AH,AL			; SAVE RESULTS
	IN	AL,INTB01		; READ 2ND IMR

	OR	AH,AL			; BOTH IMR = 0?
	JNZ	D6			; GO TO ERR ROUTINE IF NOT 0

	MOV	AL,25H			;<><><><><><><><><><><><><><>
	OUT	MFG_PORT,AL		;<><><>CHECKPOINT 25 <><><><>

	MOV	AL,0FFH 		; DISABLE DEVICE INTERRUPTS
	OUT	INTA01,AL		; WRITE TO IMR
	OUT	INTB01,AL		; WRITE TO 2ND IMR
	JMP	SHORT $+2		; IO DELAY
	IN	AL,INTA01		; READ IMR
	MOV	AH,AL			; SAVE RESULTS
	IN	AL,INTB01		; READ 2ND IMR

	ADD	AX,1			; ALL IMR BITS ON?
	JNZ	D6			; NO - GO TO ERR ROUTINE

;----- CHECK FOR HOT INTERRUPTS

;----- INTERRUPTS ARE MASKED OFF.  CHECK THAT NO INTERRUPTS OCCUR.

	MOV	INTR_FLAG,AL		; CLEAR INTERRUPT FLAG

	MOV	AL,26H			;<><><><><><><><><><><><><><>
	OUT	MFG_PORT,AL		;<><><>CHECKPOINT 26 <><><><>

	STI				; ENABLE EXTERNAL INTERRUPTS
	SUB	CX,CX			; WAIT 1 SEC FOR ANY INTRS THAT
D4:	LOOP	D4			; MIGHT OCCUR
D5:	LOOP	D5
	CMP	INTR_FLAG,00H		; DID ANY INTERRUPTS OCCUR?
	JZ	D7			; NO - GO TO NEXT TEST

D6:	MOV	MFG_ERR_FLAG,05H	; <><><><><><><><><><><><><><>
					; <><>CHECKPOINT 5<><><><><><>
	MOV	SI,OFFSET E0		; DISPLAY 101 ERROR
D6A:	CALL	E_MSG
	CLI
	HLT				; HALT THE SYSTEM

;-------CHECK THE CONVERTING LOGIC

D7:	MOV	AL,27H			;<><><><><><><><><><><><><><>
	OUT	MFG_PORT,AL		;<><><>CHECKPOINT 27 <><><><>

	MOV	AX,0AA55H		;
	OUT	MFG_PORT+2,AX		; WRITE A WORD
	IN	AL,MFG_PORT+2		;  GET THE FIRST BYTE
	XCHG	AL,AH			;  SAVE IT
	JMP	SHORT $+2		; IO DELAY
	IN	AL,MFG_PORT+3		;  GET THE SECOND BYTE
	CMP	AX,55AAH		; IS IT OK?
	JZ	D7_A			; GO IF YES

	MOV	SI,OFFSET CM4_A 	; DISPLAY 106 ERROR
	JMP	D6A

;------- CHECK FOR HOT NMI INTERRUPTS WITHOUT IO/RAM PARITY ENABLED

D7_A:
	SUB	AL,AL			; SET FLAG TO ZERO
	OUT	MFG_PORT,AL		; SAVE IT

	MOV	AL,0FH			; TURN ON NMI
	OUT	CMOS_PORT,AL		;
	MOV	CX,00FFH		; DELAY
D7_B:	LOOP	D7_B			;
	MOV	AL,8FH			; TURN OFF NMI
	OUT	CMOS_PORT,AL		;
	IN	AL,MFG_PORT		; ANY NMI?
	OR	AL,AL			;
	JZ	D7_C			; CONTINUE IF NOT

	MOV	AL,28H			;<><><><><><><><><><><><><><>
	OUT	MFG_PORT,AL		;<><><>CHECKPOINT 28 <><><><>


	MOV	SI,OFFSET CM4_B 	; DISPLAY 107 ERROR
	JMP	D6A

;------- TEST THE DATA BUS TO TIMER 2

D7_C:	MOV	AL,29H			;<><><><><><><><><><><><><><>
	OUT	MFG_PORT,AL		;<><><>CHECKPOINT 29 <><><><>
	IN	AL,PORT_B			; GET CURRENT SETTING OF PORT
	MOV	AH,AL				; SAVE THAT SETTING
	JMP	SHORT $+2			; IO DELAY
	AND	AL,0FCH 			; INSURE SPEAKER OFF
	OUT	PORT_B,AL

	MOV	AL,10110000B			; SEL TIM 2,LSB,MSB,BINARY,MODE 0
	OUT	TIMER+3,AL			; WRITE THE TIMER MODE REG
	JMP	SHORT $+2			; IO DELAY
	MOV	AX,0AA55H			; WRITE AN AA55
	OUT	TIMER+2,AL			; WRITE TIMER 2 CNT - LSB
	JMP	SHORT $+2			; IO DELAY
	MOV	AL,AH
	OUT	TIMER+2,AL			; WRITE TIMER 2 CNT - MSB

	JMP	SHORT $+2			; IO DELAY
	IN	AL,TIMER+2			; GET THE LSB
	XCHG	AH,AL				; SAVE IT

	JMP	SHORT $+2			; IO DELAY
	IN	AL,TIMER+2			; GET THE MSB
	CMP	AX,055AAH			; BUS OK?
	JZ	D7_D				; GO IF OK

	MOV	SI,OFFSET CM4_C 	; DISPLAY 108 ERROR
	JMP	D6A			;

;--------------------------------------------------------
; TEST.18						:
;	8254 TIMER CHECKOUT				:
; DESCRIPTION						:
;	VERIFY THAT THE SYSTEM TIMER (0) DOESN'T COUNT  :
;	TOO FAST OR TOO SLOW.				:
;--------------------------------------------------------

D7_D:	MOV	AL,2AH			;<><><><><><><><><><><><><><>
	OUT	MFG_PORT,AL		;<><><>CHECKPOINT 2A <><><><>
	CLI				;
	MOV	AL,0FEH 		; MASK ALL INTRS EXCEPT LVL 0
	OUT	INTA01,AL		; WRITE THE 8259 IMR
	MOV	AL,00010000B		; SEL TIM 0, LSB, MODE 0, BINARY
	OUT	TIM_CTL,AL		; WRITE TIMER CONTROL MODE REG
	MOV	CX,16H*2		; SET PGM LOOP CNT
					;
	JMP	SHORT $+2		; IO DELAY
	MOV	AL,CL			; SET TIMER 0 CNT REG
	OUT	TIMER0,AL		; WRITE TIMER 0 CNT REG
	STI				;
D8:	TEST	INTR_FLAG,01H
					; DID TIMER 0 INTERRUPT OCCUR?
	JNZ	D9			; YES - CHECK TIMER OP FOR SLOW TIME
	LOOP	D8			; WAIT FOR INTR FOR SPECIFIED TIME

	MOV	MFG_ERR_FLAG,02H	;<><><><><><><><><><><><><><>
					;<><>TIMER CHECKPOINT (2)<>


D8_A:	MOV	SI,OFFSET E0_A		; DISPLAY 102 ERROR
	JMP	D6A			; TIMER 0 INTERRUPT DIDN'T OCCUR - ERR

D9:	MOV	AL,2BH			;<><><><><><><><><><><><><><>
	OUT	MFG_PORT,AL		;<><><>CHECKPOINT 2B <><><><>

	CLI				;
	MOV	CL,12			; SET PGM LOOP CNT
	MOV	AL,0FFH 		; WRITE TIMER 0 CNT REG
	OUT	TIMER0,AL
	MOV	INTR_FLAG,0		; RESET INTR RECEIVED FLAG
	MOV	AL,0FEH 		; REENABLE TIMER 0 INTERRUPTS
	OUT	INTA01,AL
	STI
D10:	TEST	INTR_FLAG,01H		; DID TIMER 0 INTERRUPT OCCUR?
	JNZ	D8_A			; YES - TIMER CNTING TOO FAST, ERR
	LOOP	D10			; WAIT FOR INTR FOR SPECIFIED TIME

;------- WAIT FOR INTERRUPT

	SUB	CX,CX			;

	MOV	AL,2CH			;<><><><><><><><><><><><><><>
	OUT	MFG_PORT,AL		;<><><>CHECKPOINT 2C <><><><>

D11:	TEST	INTR_FLAG,01H		; DID TIMER 0 INTERRUPT OCCUR?
	JNZ	D12			; GO IF YES
	LOOP	D11			; TRY AGAIN

	MOV	SI,OFFSET E0_B		; DISPLAY 103 ERROR
	JMP	D6A			; ERROR IF NOT

;------ SETUP TIMER 0 TO MODE 3

D12:	CLI				;
	MOV	AL,0FFH 		; DISABLE ALL DEVICE INTERRUPTS
	OUT	INTA01,AL
	MOV	AL,36H			; SEL TIM 0,LSB,MSB,MODE 3
	OUT	TIMER+3,AL		; WRITE TIMER MODE REG
	JMP	SHORT $+2		; IO DELAY
	MOV	AL,0
	OUT	TIMER+0,AL		; WRITE LSB TO TIMER 0 REG
	JMP	SHORT $+2		; IO DELAY
	OUT	TIMER+0,AL		; WRITE MSB TO TIMER 0 REG
	;====================================
;------- CHECK 8042 FOR LAST COMMAND ACCEPTED
	;====================================
	SUB	CX,CX			; SET WAIT TIME
	MOV	AL,2DH			;<><><><><><><><><><><><><><>
	OUT	MFG_PORT,AL		;<><><>CHECKPOINT 2D <><><><>
D13:	IN	AL,STATUS_PORT		; GET THE 8042 STATUS
	TEST	AL,INPT_BUF_FULL	; HAS THE LAST COMMAND BEEN ACCEPTED?
	JZ	E19			; GO IF YES
	LOOP	D13			; TRY AGAIN
;-------- ERROR EXIT (MSG 105)

	MOV	SI,OFFSET CM4		; PRINT 105 ERROR
	JMP	D6A			; GO ERROR HALT

;--------------------------------------------------------
; TEST.19						:
;	ADDITIONAL READ/WRITE STORAGE TEST		:
;	++++ MUST RUN IN PROTECTED MODE ++++		:
; DESCRIPTION						:
;	WRITE/READ DATA PATTERNS TO ANY READ/WRITE	:
;	STORAGE AFTER THE FIRST 64K.  STORAGE		:
;	ADDRESSABILITY IS CHECKED.			:
;--------------------------------------------------------
	ASSUME	DS:DATA
E19:
	CALL	DDS				; SET DATA SEGMENT
	MOV	AL,2FH				;<><><><><><><><><><><><><><>
	OUT	MFG_PORT,AL			;<><><>CHECKPOINT 2F <><><><>

	CMP	RESET_FLAG,1234H		; WARM START?
	JNE	E19A				; GO IF NOT
	JMP	SHUT2				; GO TO NEXT TEST IF WARM START

;------- SET SHUTDOWN RETURN 2

E19A:	MOV	AL,30H				;<><><><><><><><><><><><><><>
	OUT	MFG_PORT,AL			;<><><>CHECKPOINT 30 <><><><>


	MOV	AL,SHUT_DOWN			; ADDR FOR SHUTDOWN BYTE
	OUT	CMOS_PORT,AL			;
	MOV	AL,2				; SECOND ENTRY IN SHUTDOWN TABLE
	JMP	SHORT $+2			; IO DELAY
	OUT	CMOS_PORT+1,AL			;
	;---------------------
;------- ENABLE PROTECTED MODE
	;---------------------
	MOV	SP,POST_SS			; SET STACK FOR SYSINIT1
	MOV	SS,SP				;
	MOV	SP,POST_SP			;

	CALL	SYSINIT1			 ; GO ENABLE PROTECTED MODE

	MOV	AL,31H			;<><><><><><><><><><><><><><>
	OUT	MFG_PORT,AL		;<><><>CHECKPOINT 31 <><><><>

;------- SET TEMPORARY STACK

	MOV	AX,GDT_PTR			;
	MOV	ES,AX				;
	MOV	ES:SS_TEMP.BASE_LO_WORD,0
	MOV	BYTE PTR ES:(SS_TEMP.BASE_HI_BYTE),0
	MOV	SI,SS_TEMP
	MOV	SS,SI
	MOV	SP,MAX_SEG_LEN-2

;------- DATA SEGMENT TO SYSTEM DATA AREA

	MOV	AX,RSDA_PTR			; POINT TO DATA AREA
	MOV	DS,AX				;

	MOV	AL,PRTY_CHK			; SET CHECK PARITY
	OUT	DMA_PAGE+6,AL			; SAVE WHICH CHECK TO USE

;------- PRINT 64 K BYTES OK

E20A:	MOV	AX,16*4 			; STARTING AMT. OF MEMORY OK
	PUSH	AX				; SAVE MEMORY OK SIZE
	JMP	PRT_SIZ 			; POST MESSAGE

;-------- IS CMOS GOOD?

E20B:	MOV	AL,DIAG_STATUS		; DETERMINE THE CONDITION OF CMOS
	OUT	CMOS_PORT,AL		;
	JMP	SHORT $+2		; IO DELAY
	IN	AL,CMOS_PORT+1		; GET THE CMOS STATUS
	PUSH	AX			; SAVE CMOS STATUS

;-------- GET THE MEMORY SIZE DETERMINED (PREPARE BX FOR BAD CMOS)

	MOV	AL,M_SIZE_HI		; GET THE HIGH BYTE
	OUT	CMOS_PORT,AL		;
	JMP	SHORT $+2		; IO DELAY
	IN	AL,CMOS_PORT+1		; HIGH BYTE
	XCHG	AH,AL			; SAVE HIGH BYTE
	MOV	AL,M_SIZE_LO		; GET THE LOW BYTE
	OUT	CMOS_PORT,AL		;
	JMP	SHORT $+2		; IO DELAY
	IN	AL,CMOS_PORT+1		; LOW BYTE
	MOV	BX,MEMORY_SIZE		; PRE LOAD THE MEMORY SIZE
	ADD	BX,AX			; SET TOTAL MEMORY SIZE
	MOV	WORD PTR KB_FLAG,BX	; SAVE THE TOTAL SIZE
	POP	AX			; RESTORE CMOS STATUS

	TEST	AL,0C0H 		; CMOS OK?
	JZ	E20B0			; GO IF YES
	JMP	E20C			; DEFAULT IF NOT
E20B0:
;-------- GET THE BASE 0->640K MEMORY SIZE FROM CONFIG IN CMOS

	MOV	AL,M1_SIZE_HI		; GET THE HIGH BYTE
	OUT	CMOS_PORT,AL		;
	JMP	SHORT $+2		; IO DELAY
	IN	AL,CMOS_PORT+1		; HIGH BYTE
	XCHG	AH,AL			; SAVE HIGH BYTE
	MOV	AL,M1_SIZE_LO		; GET THE LOW BYTE
	OUT	CMOS_PORT,AL		;
	JMP	SHORT $+2		; IO DELAY
	IN	AL,CMOS_PORT+1		; LOW BYTE
	CMP	MEMORY_SIZE,AX		; IS MEMORY SIZE GREATER THAN CONFIG?
	JZ	E20B1			; GO IF EQUAL

;------- SET MEMORY SIZE DETERMINE NOT EQUAL TO CONFIG

	PUSH	AX			; SAVE AX
	MOV	AL,DIAG_STATUS		;
	OUT	CMOS_PORT,AL		; ADDRESS THE STATUS BYTE
	JMP	SHORT $+2		; IO DELAY
	IN	AL,CMOS_PORT+1		; GET THE STATUS
	OR	AL,W_MEM_SIZE		; SET CMOS FLAG
	XCHG	AL,AH			; SAVE AL
	MOV	AL,DIAG_STATUS		;
	OUT	CMOS_PORT,AL		;
	XCHG	AL,AH			; RESTORE AL
	JMP	SHORT $+2		; IO DELAY
	OUT	CMOS_PORT+1,AL		;
	POP	AX			; RESTORE AX
	CMP	MEMORY_SIZE,AX		; IS MEMORY SIZE GREATER THAN CONFIG?
E20B1:	JA	E20C			; DEFAULT TO MEM SIZE DET IF YES
	MOV	BX,AX			; SET BASE MEMORY SIZE
	CMP	AX,513			; CHECK IF BASE RAM LESS 512K
	JB	NO_640			; GO IF YES
	MOV	AL,INFO_STATUS		; SET 640K BASE RAM BIT
	OUT	CMOS_PORT,AL		;
	JMP	SHORT $+2		; IO DELAY
	IN	AL,CMOS_PORT+1		; GET THE CURRENT STATUS
	OR	AL,M640K		; TURN ON 640K BIT IF NOT ALREADY ON
	XCHG	AL,AH			; SAVE THE CURRENT DIAG STATUS
	MOV	AL,INFO_STATUS		;
	OUT	CMOS_PORT,AL		; ADDR THE STATUS BYTE
	XCHG	AL,AH			; RESTORE THE STATUS
	JMP	SHORT $+2		; IO DELAY
	OUT	CMOS_PORT+1,AL		;

;-------- CHECK MEMORY SIZE ABOVE 640K FROM CONFIG

NO_640:
	MOV	AL,M2_SIZE_HI		; GET THE HIGH BYTE
	OUT	CMOS_PORT,AL		;
	JMP	SHORT $+2		; IO DELAY
	IN	AL,CMOS_PORT+1		; HIGH BYTE
	XCHG	AH,AL			; SAVE HIGH BYTE
	MOV	AL,M2_SIZE_LO		; GET THE LOW BYTE
	OUT	CMOS_PORT,AL		;
	JMP	SHORT $+2		; IO DELAY
	IN	AL,CMOS_PORT+1		; LOW BYTE
	MOV	CX,AX			; SAVE THE ABOVE 640K RAM SIZE
;------- ABOVE 640K SIZE FROM MEMORY SIZE DETERMINE
;------- CX=CONFIG  AX=MEMORY SIZE DETERMINE
	MOV	AL,M_SIZE_HI		; GET THE HIGH BYTE
	OUT	CMOS_PORT,AL		;
	JMP	SHORT $+2		; IO DELAY
	IN	AL,CMOS_PORT+1		; HIGH BYTE
	XCHG	AH,AL			; SAVE HIGH BYTE
	MOV	AL,M_SIZE_LO		; GET THE LOW BYTE
	OUT	CMOS_PORT,AL		;
	JMP	SHORT $+2		; IO DELAY
	IN	AL,CMOS_PORT+1		; LOW BYTE
;------- WHICH IS GREATER
;------- AX=MEMORY SIZE DETERMINE CX=CONFIG (ABOVE 640)  BX=SIZE (BELOW 640)
	CMP	CX,AX			; IS CONFIG EQUAL TO DETERMINED?
	JZ	SET_MEM1		; GO IF EQUAL
;------- SET MEMORY SIZE DETERMINE NOT EQUAL TO CONFIG
	PUSH	AX			; SAVE AX
	MOV	AL,DIAG_STATUS		;
	OUT	CMOS_PORT,AL		; ADDRESS THE STATUS BYTE
	JMP	SHORT $+2		; IO DELAY
	IN	AL,CMOS_PORT+1		; GET THE STATUS
	OR	AL,W_MEM_SIZE		; SET CMOS FLAG
	XCHG	AL,AH			; SAVE AL
	MOV	AL,DIAG_STATUS		;
	OUT	CMOS_PORT,AL		;
	XCHG	AL,AH			; RESTORE AL
	JMP	SHORT $+2		; IO DELAY
	OUT	CMOS_PORT+1,AL		;
	POP	AX			; RESTORE AX

SET_MEM1:
	CMP	CX,AX			; IS CONFIG GREATER THAN DETERMINED?
	JA	SET_MEM 		;  GO IF YES
	MOV	CX,AX			; USE MEMORY SIZE DETERMINE IF NOT
SET_MEM:
	ADD	BX,CX			; SET TOTAL MEMORY SIZE
	MOV	WORD PTR KB_FLAG,BX	; SAVE TOTAL SIZE FOR LATER TESTING
E20C:
E20D:	SUB	BX,16*4 			; 1ST 64K ALREADY DONE
	MOV	CL,06H
	SHR	BX,CL				; DIVIDE BY 64
	PUSH	BX				; SAVE COUNT OF 64K BLOCKS
	;========================
;------- MODIFY DESCRIPTOR TABLES
	;========================
						;
	MOV	AX,GDT_PTR			; MODIFY THE DESCRIPTOR TABLE
	MOV	ES,AX				;
	;----------------------------------------
;------- SET TEMP ES DESCRIPTOR 64K SEGMENT LIMIT
	;----------------------------------------

	MOV	ES:ES_TEMP.SEG_LIMIT,MAX_SEG_LEN

;------- CPL0, DATA ACCESS RIGHTS

	MOV	BYTE PTR ES:(ES_TEMP.DATA_ACC_RIGHTS),CPL0_DATA_ACCESS

;------- START WITH SEGMENT 010000 (SECOND 64K)

	MOV	BYTE PTR ES:(ES_TEMP.BASE_HI_BYTE),0
	MOV	ES:ES_TEMP.BASE_LO_WORD,0

	;----------------------------------------
;------- SET TEMP DS DESCRIPTOR 64K SEGMENT LIMIT
	;----------------------------------------

	MOV	ES:DS_TEMP.SEG_LIMIT,MAX_SEG_LEN

;------- CPL0, DATA ACCESS RIGHTS

	MOV	BYTE PTR ES:(DS_TEMP.DATA_ACC_RIGHTS),CPL0_DATA_ACCESS

;------- START WITH SEGMENT 010000

	MOV	BYTE PTR ES:(DS_TEMP.BASE_HI_BYTE),0
	MOV	ES:DS_TEMP.BASE_LO_WORD,0

;------- TEMPORARY SEGMENT SAVE IN DMA PAGE REGISTER

	SUB	AL,AL
	OUT	DMA_PAGE+4,AL		; HIGH BYTE OF LOW WORD OF SEGMENT
	OUT	DMA_PAGE+5,AL		; LOW BYTE OF LOW WORD OF SEGMENT
	INC	AL			; SET HIGH BYTE OF SEGMENT WORD
	OUT	DMA_PAGE+3,AL		; HIGH BYTE OF SEGMENT

;------- POINT TO NEXT BLOCK OF 32K WORDS

E21:	MOV	AX,GDT_PTR		; POINT TO START OF DESCR TABLE
	MOV	DS,AX			;
	INC	BYTE PTR DS:(DS_TEMP.BASE_HI_BYTE)
	INC	BYTE PTR DS:(ES_TEMP.BASE_HI_BYTE)

;-------- CHECK FOR END OF 256K PLANAR RAM

	CMP	BYTE PTR DS:(DS_TEMP.BASE_HI_BYTE),04H
	JB	E21_0			; GO IF STILL BASE RAM
	PUSH	DS			; SAVE THE CURRENT DATA SEGMENT
	MOV	AX,RSDA_PTR		; POINT TO POST DATA SEGMENT
	MOV	DS,AX			;
	MOV	AL,MFG_TST		; GET THE JUMPER INFO
	POP	DS			; RESTORE DS
	TEST	AL,BASE_RAM		; CHECK IF SECOND 256K ON BASE PLANAR
	JNZ	E21_0			; GO IF YES
	MOV	AL,IO_CHK		; SET IO CHANNEL CHECK TEST
	OUT	DMA_PAGE+6,AL

;------- CHECK END OF FIRST 516K OR 640K (END OF BASE RAM)

E21_0:	MOV	AL,INFO_STATUS		; SET 640K BASE RAM BIT
	OUT	CMOS_PORT,AL		;
	JMP	SHORT $+2		; IO DELAY
	IN	AL,CMOS_PORT+1		; GET THE CURRENT STATUS

;-------- CHECK FOR END OF 512K PLANAR RAM

	CMP	BYTE PTR DS:(DS_TEMP.BASE_HI_BYTE),08H
	JB	E12_A			; GO IF STILL BASE RAM

;-------- SET USE TEST IO CHECK

	XCHG	AL,AH			; SAVE AL
	MOV	AL,IO_CHK		;
	OUT	DMA_PAGE+6,AL		;
	XCHG	AL,AH			; RESTORE AL

;------- CHECK FOR 640K BASE RAM (128K IO CARD)

E12_A:	TEST	AL,M640K		; IS 640K BASE INSTALLED?
	JZ	E12_B			; GO IF NO

	CMP	BYTE PTR DS:(DS_TEMP.BASE_HI_BYTE),0AH
	JNZ	NEXT1
	JMP	E12_C			; CONTINUE

E12_B:	CMP	BYTE PTR DS:(DS_TEMP.BASE_HI_BYTE),08H
	JNZ	NEXT1

;------- DO ADDITIONAL STORAGE ABOVE 1 MEG

E12_C:	MOV	BYTE PTR DS:(DS_TEMP.BASE_HI_BYTE),10H
	MOV	BYTE PTR DS:(ES_TEMP.BASE_HI_BYTE),10H

;------- SAVE BASE_HI_BYTE IN DMA PAGE REGISTERS 3

NEXT1:	MOV	AL,BYTE PTR DS:(DS_TEMP.BASE_HI_BYTE)
	OUT	DMA_PAGE+3,AL		; SAVE THE HIGH BYTE OF SEGMENT
					;  FOR POSSIBLE ERROR

;------- CHECK FOR TOP OF RAM (FE0000) 16MEG

	CMP	BYTE PTR DS:(ES_TEMP.BASE_HI_BYTE),0FEH ; TOP OF RAM?
	JNZ	NEXT			; GO IF NOT
	JMP	KB_LOOP3		; GO NEXT TEST

;------- SET ES AND DS REGISTERS

NEXT:	MOV	AX,DS_TEMP
	MOV	DS,AX
	MOV	AX,ES_TEMP
	MOV	ES,AX

	MOV	AL,31H			;<><><><><><><><><><><><><><>
	OUT	MFG_PORT,AL		;<><><>CHECKPOINT 31 <><><><>

	MOV	CX,2000H*4		; SET COUNT FOR 32K WORDS
	CALL	STGTST_CNT
	JZ	N1			; SKIP IF OK
	JMP	E21A			; GO PRINT ERROR
N1:	POP	CX			; POP CX TO GET AX
	POP	AX			; RECOVER TESTED MEMORY

;------- WRITE THE CURRENT SIZE FOR (ADDRESS LINES 23-17 TEST) USED LATER

	SUB	DI,DI			; POINT TO BEGINNING OR A BLOCK
	STOSW				; WRITE THE CURRENT SIZE
					;  AT THE STARTING ADDRESS
	ADD	AX,16*4
	PUSH	AX			; SAVE TESTED MEMORY
	PUSH	CX			; SAVE LOOP COUNT

PRT_SIZ:
	PUSH	AX			;
	MOV	BX,10			; SET DECIMAL CONVERT
;------- CONVERT AND SAVE
	MOV	CX,5			; OF 5 NIBBLES XX,XXX KB
	SUB	DI,DI			; CRT BUFFER POSITION
DECIMAL_LOOP:
	XOR	DX,DX
	DIV	BX			; DIVIDE BY 10
	OR	DL,30H			; MAKE INTO ASCII
	PUSH	DX			; SAVE
	LOOP	DECIMAL_LOOP		;
;------- DISPLAY LAST OK MEMORY 	;
	MOV	CX,5			;
PRT_DEC_LOOP:				;
	POP	AX			; RECOVER A NUMBER
	CALL	PROT_PRT_HEX
	INC	DI			; POINT TO CRT BUFF
	LOOP	PRT_DEC_LOOP
	MOV	CX,6
	MOV	SI,OFFSET F3B		; PRINT ' KB OK'
KB_LOOP:
	MOV	AL,CS:[SI]
	INC	SI
	CALL	PROT_PRT_HEX
	INC	DI			; INCREMENT BUFF PTR
	LOOP	KB_LOOP
	POP	AX			; RECOVER WORK REGS
	CMP	AX,16*4 		; FIRST PASS?
	JNZ	KB_LOOP1		; GO IF NOT
	JMP	E20B
KB_LOOP1:
	POP	CX			; RECOVER 64K BLOCK COUNT
	POP	AX			;
	LOOP	KB_LOOP2		; LOOP TILL ALL MEM. CHECKED
	JMP	KB_LOOP3		; CONTINUE
KB_LOOP2:
	PUSH	AX			;
	PUSH	CX			; SAVE LOOP COUNT
	JMP	E21			; LOOP TILL ALL MEM CHECKED


KB_LOOP3:
	;=======================
;------- ADDRESS LINE 16-23 TEST
	;=======================

;------- CALCULATE NUMBER OF  64K BLOCKS

	MOV	AX,64				; START AT SECOND 64K
	PUSH	AX				; SAVE STARTING ADDR

	MOV	AX,RSDA_PTR			; GET THE MEMORY SIZE
	MOV	DS,AX				;

	MOV	BX,WORD PTR KB_FLAG		; GET THE TOTAL MEMORY SIZE
						; KB_FLAG USED AS TEMP STORAGE
	SUB	BX,64				; START AT SECOND 64K BOUNDRY
	MOV	CL,06H				; DIVIDE BY 64K
	SHR	BX,CL				;
	PUSH	BX				; SAVE LOOP COUNT

;------- INITIALIZE DS DESCRIPTOR

	MOV	AX,GDT_PTR
	MOV	ES,AX
	MOV	BYTE PTR ES:(DS_TEMP.BASE_HI_BYTE),0
	MOV	ES:DS_TEMP.BASE_LO_WORD,0

;------- TEMPORARY SEGMENT SAVE IN DMA PAGE REGISTER

	SUB	AL,AL
	OUT	DMA_PAGE+4,AL		; HIGH BYTE OF LOW WORD OF SEGMENT
	OUT	DMA_PAGE+5,AL		; LOW BYTE OF LOW WORD OF SEGMENT
	MOV	AL,01H			; SET HIGH BYTE OF SEGMENT WORD
	OUT	DMA_PAGE+3,AL		; HIGH BYTE OF SEGMENT

;------- POINT TO NEXT BLOCK OF 64K

E21_A:

	MOV	AL,33H			;<><><><><><><><><><><><><><>
	OUT	MFG_PORT,AL		;<><><>CHECKPOINT 33 <><><><>
	ADD	BYTE PTR ES:(DS_TEMP.BASE_HI_BYTE),01

;------- CHECK END OF FIRST 516K OR 640K (END OF BASE RAM)

	MOV	AL,INFO_STATUS		; SET 640K BASE RAM BIT
	OUT	CMOS_PORT,AL		;
	JMP	SHORT $+2		; IO DELAY
	IN	AL,CMOS_PORT+1		; GET THE CURRENT STATUS
	TEST	AL,M640K		; CHECK FOR 640K BASE RAM
	JZ	NEXT_A1 		; GO IF ONLY 512K

;-------- CHECK FOR END OF 512K PLANAR RAM

	CMP	BYTE PTR ES:(DS_TEMP.BASE_HI_BYTE),0AH
	JNZ	NEXT_A			; GO IF STILL BASE RAM
	JMP	NEXT_A2 		;
NEXT_A1:CMP	BYTE PTR ES:(DS_TEMP.BASE_HI_BYTE),08H
	JNZ	NEXT_A

;------- DO ADDITIONAL STORAGE ABOVE 1 MEG

NEXT_A2:MOV	BYTE PTR ES:(DS_TEMP.BASE_HI_BYTE),10H

;------- SET USE TEST IO CHECK

	MOV	AL,IO_CHK		;
	OUT	DMA_PAGE+6,AL		;

NEXT_A: MOV	AL,BYTE PTR ES:(DS_TEMP.BASE_HI_BYTE)

;------- DMA PAGE REGISTERS 3

	OUT	DMA_PAGE+3,AL		; SAVE THE HIGH BYTE OF SEGMENT
					;  FOR POSSIBLE ERROR

;------- CHECK FOR TOP OF RAM (FE0000) 16MEG

	CMP	BYTE PTR ES:(DS_TEMP.BASE_HI_BYTE),0FEH ; TOP OF RAM?
	JNZ	NEXT_B			; GO IF NOT
	JMP	KB_LOOP_3		; GO NEXT TEST

;------- SET DS REGISTER

NEXT_B: MOV	AX,DS_TEMP
	MOV	DS,AX
	SUB	DI,DI			; POINT TO START OF BLOCK
	MOV	AX,DS:[DI]		; GET THE VALUE OF THIS BLOCK
	MOV	DX,AX			; SAVE
	MOV	SI,DI			; SET SI FOR POSSIBLE ERROR
	SUB	AX,AX			; CLEAR RAM LOCATION
	MOV	DS:[DI],AX		;
;------- ALLOW CRT TIME TO DISPLAY MSG
	SUB	CX,CX			;
Z2:	LOOP	Z2
	POP	CX			; GET THE LOOP COUNT
	POP	AX			; RECOVER TESTED MEMORY
	PUSH	AX			; SAVE TESTED MEMORY
	PUSH	CX			; SAVE LOOP COUNT
	CMP	AX,DX			; DOES THE BLOCK ID MATCH
	MOV	AX,DX			; GET THE BLOCK ID FOR POSSIBLE ERROR
	JNZ	E21A			; GO PRINT ERROR
	POP	CX			; POP CX TO GET AX
	POP	AX			; RECOVER TESTED MEMORY
	ADD	AX,64			; 64K INCREMENTS
	PUSH	AX			; SAVE TESTED MEMORY
	PUSH	CX			; SAVE LOOP COUNT

	PUSH	AX			;
	MOV	BX,10			; SET DECIMAL CONVERT

;------- CONVERT AND SAVE

	MOV	CX,5			; OF 5 NIBBLES XX,XXX KB
	SUB	DI,DI			; CRT BUFFER POSITION
DEC_LOOP:
	XOR	DX,DX
	DIV	BX			; DIVIDE BY 10
	OR	DL,30H			; MAKE INTO ASCII
	PUSH	DX			; SAVE
	LOOP	DEC_LOOP		;
;------- DISPLAY LAST OK MEMORY 	;
	MOV	CX,5			;
PRT_DEC:				;
	POP	AX			; RECOVER A NUMBER
	CALL	PROT_PRT_HEX
	INC	DI			; POINT TO CRT BUFF
	LOOP	PRT_DEC
	MOV	CX,6
	MOV	SI,OFFSET F3B		; PRINT ' KB OK'
KB_LOOP_1:
	MOV	AL,CS:[SI]
	INC	SI
	CALL	PROT_PRT_HEX
	INC	DI			; INCREMENT BUFF PTR
	LOOP	KB_LOOP_1
	POP	AX			; RECOVER WORK REGS
	POP	CX			; RECOVER 64K BLOCK COUNT
	POP	AX			;
	LOOP	KB_LOOP_2		; LOOP TILL ALL MEM. CHECKED

;-------- CHECK PARITY

	OUT	DMA_PAGE+8,AL		; SAVE AX
	XCHG	AL,AH			;
	OUT	DMA_PAGE+9,AL		;
	IN	AL,PORT_B		; CHECK FOR IO OR PAR CHECK
	AND	AL,PARITY_ERR		; STRIP UNWANTED BITS
	XCHG	AL,AH			; SAVE ERROR
	IN	AL,DMA_PAGE+6		; CHECK FOR R/W OR IO ERR
	AND	AH,AL			;
	IN	AL,DMA_PAGE+9		; RESTORE AX
	XCHG	AL,AH			;
	IN	AL,DMA_PAGE+8		;
	JNZ	E21A			; GO IF PARITY ERROR

	JMP	KB_LOOP_3		; CONTINUE
KB_LOOP_2:
	PUSH	AX			;
	PUSH	CX			; SAVE LOOP COUNT

	JMP	E21_A			; CONTINUE TILL DONE

;------- BACK TO REAL MODE
KB_LOOP_3:
	MOV	AL,34H			;<><><><><><><><><><><><><><>
	OUT	MFG_PORT,AL		;<><><>CHECKPOINT 34 <><><><>

	JMP	PROC_SHUTDOWN		; BACK TO REAL MODE
					; NEXT TEST VIA JUMP TABLE (SHUT2)

;----- PRINT FAILING ADDRESS AND XOR'ED PATTERN IF DATA COMPARE ERROR

;----- USE DMA PAGE REGISTERS AS TEMPORARY SAVE AREA FOR ERROR
;      SET SHUTDOWN 3

E21A:	OUT	DMA_PAGE+1,AL		; SAVE FAILING BIT PATTERN (LOW BYTE)
	MOV	AL,AH			; SAVE HIGH BYTE
	JMP	SHORT $+2		; IO DELAY
	OUT	DMA_PAGE+2,AL		;
	MOV	AX,SI			; GET THE FAILING OFFSET
	OUT	DMA_PAGE+5,AL		;
	XCHG	AH,AL			;
	JMP	SHORT $+2		; IO DELAY
	OUT	DMA_PAGE+4,AL		;

;------- CLEAR IO CH CHK OR R/W PAR CHK

	SUB	SI,SI			; WRITE TO FAILING BLOCK
	STOSW				;
	IN	AL,PORT_B		;
	OR	AL,RAM_PAR_OFF		; TOGGLE IO/PAR CHECK ENABLE
	JMP	SHORT $+2		; IO DELAY
	OUT	PORT_B,AL		;
	AND	AL,RAM_PAR_ON
	JMP	SHORT $+2		; IO DELAY
	OUT	PORT_B,AL
	;===============
;------- SET MEMORY SIZE
	;===============
	MOV	AX,RSDA_PTR		; SET THE DATA SEGMENT
	MOV	DS,AX			; IN PROTECTED MODE

;------- GET THE DIAG_STATUS FROM CMOS

	MOV	AL,DIAG_STATUS		;
	OUT	CMOS_PORT,AL		;
	JMP	SHORT $+2		; IO DELAY
	IN	AL,CMOS_PORT+1		;
	MOV	BL,AL			; SAVE THE STATUS BYTE

	MOV	AL,INFO_STATUS		;
	OUT	CMOS_PORT,AL		;
	JMP	SHORT $+2		; IO DELAY
	IN	AL,CMOS_PORT+1		;
	MOV	BH,AL			; SAVE THE STATUS BYTE

;------- GET THE LAST OF GOOD MEMORY

	POP	CX			;
	POP	AX			; GET THE LAST OF GOOD MEMORY
	MOV	CX,AX			; SAVE IT

;------- BELOW 512K?

	CMP	AX,512			; LAST GOOD MEMORY BELOW 512K?
	JB	M3			; GO IF YES

;------- BELOW 640K?

	CMP	AX,640			; LAST GOOD MEMORY BELOW 640K?
	JB	M1			; GO IF YES

;------- 640K UP ERROR

	TEST	BH,M640K		; IS BASE RAM 640K?
	JNZ	M0			; GO IF YES
	SUB	AX,512			; 512K BASE RAM
	JMP	M2			;
M0:	SUB	AX,640			; 640K BASE RAM
	JMP	M2			;

;------- 512K TO 640K ERROR

M1:	TEST	BH,M640K		; IS BASE RAM 640K?
	JNZ	M3			; GO IF YES
	SUB	AX,512			; STRIP BASE RAM FROM IO RAM

;------- WRITE SIZE TO CMOS

M2:	MOV	CX,AX			; SAVE ADJUSTED MEMORY SIZE
	MOV	AL,M_SIZE_HI		;
	OUT	CMOS_PORT,AL		;
	MOV	AL,CH			; GET THE HIGH BYTE MEMORY SIZE
	JMP	SHORT $+2		; IO DELAY
	OUT	CMOS_PORT+1,AL		; WRITE IT
	MOV	AL,M_SIZE_LO		;
	JMP	SHORT $+2		;
	OUT	CMOS_PORT,AL		;
	MOV	AL,CL			; GET THE LOW BYTE
	JMP	SHORT $+2		; IO DELAY
	OUT	CMOS_PORT+1,AL		; WRITE IT
	JMP	M4			; CONTINUE

;------- SET BASE MEMORY SIZE

M3:	MOV	MEMORY_SIZE,AX		; TO INDICATE HOW MUCH MEM WORKING

;------- SET SHUTDOWN 3

M4:	MOV	AL,SHUT_DOWN		; ADDR FOR SHUTDOWN RETURN
	OUT	CMOS_PORT,AL		;
	MOV	AL,3			; SET RETURN 3
	JMP	SHORT $+2		; IO DELAY
	OUT	CMOS_PORT+1,AL		;

;------- SHUTDOWN

	JMP	PROC_SHUTDOWN		;
PAGE
;------- ENTRY 3 FROM PROCESSOR SHUTDOWN

;--------------------------------------------------------------------
; MEMORY ERROR REPORTING					    :
;								    :
; DESCRIPTION FOR ERRORS 201(CMP ERROR or PARITY)		    :
;		      or 202(ADDRESS LINE 0-15 ERROR)		    :
;	R/W MEMORY ERRORS WILL BE REPORTED AS FOLLOWS		    :
;								    :
;	AABBCC DDEE 201(or 202) 				    :
;	AA=HIGH BYTE OF 24 BIT ADDRESS				    :
;	BB=MIDDLE BYTE OF 24 BIT ADDRESS			    :
;	CC=LOW BYTE OF 24 BIT ADDRESS				    :
;	DD=HIGH BYTE OF XOR FAILING BIT PATTERN 		    :
;	EE=LOW BYTE OF XOR FAILING BIT PATTERN			    :
;								    :
; DESCRIPTION FOR ERROR 202 (ADDRESS LINE 00-15)		    :
;	A WORD OF FFFF IS WRITTEN AT THE FIRST WORD AND LAST WORD   :
;	OF EACH 64K BLOCK WITH ZEROS AT ALL OTHER LOCATIONS OF THE  :
;	BLOCK.	A SCAN OF THE BLOCK IS MADE TO INSURE ADDRESS LINE  :
;	0-15 ARE FUNCTIONING.					    :
;								    :
; DESCRIPTION FOR ERROR 203 (ADDRESS LINE 16-23)		    :
;	AT THE LAST PASS OF THE STORAGE TEST, FOR EACH BLOCK OF     :
;	64K, THE CURRENT STORAGE SIZE (ID) IS WRITTEN AT THE FIRST  :
;	WORD OF EACH BLOCK. IT IS USED TO DETERMINE ADDRESSING	    :
;	FAILURES.						    :
;								    :
;	AABBCC DDEE 203 					    :
;	SAME AS ABOVE EXCEPT FOR DDEE				    :
;								    :
; GENERAL DESCRIPTION FOR BLOCK ID (DDEE WILL NOW CONTAINED THE ID) :
;	DD=HIGH BYTE OF BLOCK ID				    :
;	EE=LOW BYTE OF BLOCK ID 				    :
;								    :
;	BLOCK ID	ADDRESS RANGE				    :
;	0000		000000 --> 00FFFF			    :
;	0040		010000 --> 01FFFF			    :
;	//							    :
;	0200		090000 --> 09FFFF (512->576K) IF 640K BASE  :
;			100000 --> 10FFFF (1024->1088K) IF 512K BASE:
;								    :
; EXAMPLE (640K BASE RAM + 512K IO RAM = 1152K TOTAL)		    :
;	NOTE: THE CORRECT BLOCK ID FOR THID FAILURE IS 0280 HEX.    :
;	      DUE TO AN ADDRESS FAILURE THE BLOCK ID+128K OVER-     :
;	      LAYED THE CORRECT BLOCK ID.			    :
;	00640K OK	 <-- LAST OK MEMORY			    :
;	10000 0300 202	 <-- ERROR DUE TO ADDRESS FAILURE	    :
;								    :
;								    :
; DMA PAGE REGISTERS ARE USED AS TEMPORARY SAVE AREAS FOR SEGMENT   :
; DESCRIPTOR VALUES.						    :
;--------------------------------------------------------------------

SHUT3:	MOV	AX,DATA 		; SET REAL MODE DATA SEGMENT
	MOV	DS,AX			;

;------- INIT AND SET MFG ERROR

	MOV	MFG_ERR_FLAG+1,0	; CLEAR FLAG

	OR	MFG_ERR_FLAG+1,MEM_FAIL ;<><><><><><><><><><><><><><><>
					;<><> MEMORY FAILED<><><><><><>

	MOV	AL,13			; CARRIAGE RETURN
	CALL	PRT_HEX
	MOV	AL,10
	CALL	PRT_HEX
	IN	AL,DMA_PAGE+3		; GET THE HIGH BYTE OF 24 BIT ADDRESS
	CALL	XPC_BYTE		; CONVERT AND PRINT CODE
					; CHECKPOINT 00->FE
	IN	AL,DMA_PAGE+4		; GET THE MIDDLE BYTE OF 24 BIT ADORES
	CALL	XPC_BYTE		;
	IN	AL,DMA_PAGE+5		; GET THE LOW BYTE OF 24 BIT ADDRESS
	CALL	XPC_BYTE		;
	MOV	AL,' '                  ; SPACE TO MESSAGE
	CALL	PRT_HEX 		;
	IN	AL,DMA_PAGE+2		; GET HIGH BYTE FAILING BIT PATTERN
	CALL	XPC_BYTE		; CONVERT AND PRINT CODE
	IN	AL,DMA_PAGE+1		; GET LOW BYTE FAILING BIT PATTERN
	CALL	XPC_BYTE		; CONVERT AND PRINT CODE

;-------- CHECK FOR ADDRESS ERROR

	IN	AL,MFG_PORT		; GET THE CHECKPOINT
	CMP	AL,33H			; IS IT AN ADDRESS FAILURE?
	MOV	SI,OFFSET ADERR 	; PRELOAD ADDRESS ERROR 16->23
	JZ	ERR2			; GO IF YES
	MOV	SI,OFFSET ADERR1	; PRELOAD ADDRESS ERROR 00->15
	CMP	AL,32H			; GO IF YES
	JZ	ERR2
	MOV	SI,OFFSET E1		; SETUP ADDRESS OF ERROR MSG
ERR2:	CALL	E_MSG			; PRINT ERROR MESSAGE
;-----	ENTRY FROM SHUTDOWN

SHUT2:

;--------------------------------------------------------
; TEST.20						:
;	ADDITIONAL PROTECTED (VIRTUAL MODE) TEST	:
; DESCRIPTION						:
;	THE PROCESSOR IS PUT IN PROTECTED MODE AND	:
;	THE FOLLOWING FUNCTIONS ARE VERIFIED		:
;							:
;	1. VERIFY PROTECTED MODE			:
;	   THE MACHINE STATUS IS CHECK FOR VIRTUAL MODE :
;	2. PROGRAMMED INTERRUPT TEST			:
;	   AN PROGRAMMED INTERRUPT 32 IS ISSUED AND	:
;	   AND VERIFIED 				:
;	3. EXCEPTION INT 13 TEST			:
;	   A DESCRIPTOR SEGMENT LIMIT IS SET TO ZERO	:
;	   AND A WRITE TO THAT SEGMENT IS ATTEMPTED	:
;	   AN EXCEPTION 13 IS EXPECTED AND VERIFIED	:
;	4. LDT/SDT LTR/STR TEST 			:
;	   LOAD LDT REGISTER AND VERIFY CORRECT 	:
;	   LOAD TASK REGISTER AND VERIFY CORRECT	:
;	   THEY ARE VERIFIED VIA THE STORE INSTRUCTION	:
;	5. THE CONTROL FLAGS OF THE 286 FOR DIRECTION	:
;	   ARE VERIFIED VIA THE STD AND CLD COMMANDS	:
;	   IN PROTECTED MODE				:
;	6. BOUND INSTRUCTION TEST (EXC INT 5)		:
;	   CREATE A SIGNED ARRAY INDEX WITHIN AND	:
;	   OUTSIDE THE LIMITS.	CHECK THAT NO EXC INT	:
;	   IF WITHIN LIMIT AND THAT AN EXC INT 5	:
;	   OCCURS IF OUTSIDE THE LIMITS.		:
;	7. PUSH ALL POP ALL TEST			:
;	   SET ALL GENERAL PURPOSE REGS TO DIFFERENT	:
;	   VALUES ISSUE A PUSH ALL, CLEAR THE REGS	:
;	   ISSUE A POP ALL AND VERIFY CORRECT.		:
;	8. CHECK THE VERR/VERW INSTRUCTIONS		:
;	   THE ACCESS BYTE IS SET TO READ ONLY THEN TO	:
;	   A WRITE ONLY AND THE VERR/VERW INST ARE	:
;	   VERIFIED.					:
;	9. CAUSE AN INTERRUPT 13 VIA A WRITE TO A	:
;	   READ ONLY SEGMENT				:
;      10. VERIFY THE ARPL INSTRUCTION FUNCTIONS	:
;	   SET THE RPL FIELD OF A SELECTOR AND		:
;	   VERIFY THAT CURRENT SELECTOR RPL IS SET	:
;	   CORRECTLY.					:
;      11. VERIFY THE LAR INSTRUCTION FUNCTIONS 	:
;      12. VERIFY THE LSL INSTRUCTION FUNCTIONS 	:
;      13. LOW MEG CHIP SELECT TEST			:
;--------------------------------------------------------

	JMP	POST7			; GO TEST THE 286 PROTECTED MODE

;-------- FAILURE ENTRY FROM A SHUTDOWN

SHUT7:	CALL	DDS			; ESTABLISH THE DATA SEGMENT
	IN	AL,MFG_PORT		; CHECK FOR CHIP SELECT ERROR
	CMP	AL,35H			;
	MOV	SI,OFFSET CM4_D 	; PRINT ERROR 109
	JZ	SHUT7B			; GO IF NOT
SHUT7A: MOV	SI,OFFSET VIR_ERR	; PROTECTED MODE FAILED

	OR	MFG_ERR_FLAG+1,PRO_FAIL ;<><><><><><><><><><><><><><><>
					;<><> VIRTUAL MODE FAILED<><><>

	CALL	E_MSG			; PRINT MSG
	JMP	SHUT6			;
SHUT7B: CALL	E_MSG			; PRINT MSG

	OR	MFG_ERR_FLAG+1,LMCS_FAIL;<><><><><><><><><><><><><><><>
					;<><> LOW MEG CHIP SELECT  <><>

;-------- PROTECTED MODE TEST PASSED ENTRY FROM A SHUTDOWN

SHUT6:	CALL	DDS			; PROTECTED MODE TEST PASSED
	SUB	AX,AX			; CLEAR KEYBOARD STATE FLAGS
	MOV	WORD PTR KB_FLAG,AX	;
	MOV	CX,0EH			; CLEAR PAGE REGS
	MOV	DX,DMA_PAGE+1		;
CLR_LOOP:
	SUB	AL,AL			;
	OUT	DX,AL			;
	INC	DX			;
	LOOP	CLR_LOOP		;

;------------------------------------------------
;TEST.21					:
;      KEYBOARD TEST				:
; DESCRIPTION					:
;      RESET THE KEYBOARD AND CHECK THAT SCAN	:
;      CODE 'AA' IS RETURNED TO THE CPU.        :
;      CHECK FOR STUCK KEYS.			:
;------------------------------------------------

	MOV	AL,35H			;<><><><><><><><><><><><><><>
	OUT	MFG_PORT,AL		;<><><>CHECKPOINT 35 <><><><>

	TEST	MFG_TST,LOOP_POST	; MANUFACTURING BURN IN TEST MODE?
	JNZ	F7_A
	JMP	F7			; YES - SKIP KEYBOARD TEST
F7_A:	CMP	BYTE PTR RESET_FLAG,064H ; MANUFACTURING RUN IN MODE?
	JNZ	F7_B
	JMP	F7			; YES - SKIP KEYBOARD TEST
F7_B:	MOV	AL,36H			;<><><><><><><><><><><><><><>
	OUT	MFG_PORT,AL		;<><><>CHECKPOINT 36 <><><><>
	CLI				;
	CMP	RESET_FLAG,1234H	; SOFT RESET?
	JZ	G10
	CMP	BYTE PTR RESET_FLAG,KB_OK ; CHECK FOR AA ALREADY RECEIVED
	JZ	G10			; GO IF YES
	MOV	AL,ENA_KBD		;
	CALL	C8042			; ENABLE KEYBOARD
	MOV	BH,4			; TRY 4 TIMES
LOOP1:	CALL	OBF_42			; CHECK FOR OUTPUT BUFFER FULL
	JNZ	G10			; GO IF BUFFER FULL
	DEC	BH			;
	JNZ	LOOP1			;
G10:	MOV	AL,DIS_KBD		; DISABLE KEYBOARD
	CALL	C8042			;
	IN	AL,PORT_A		; FLUSH
	MOV	AL,KYBD_CLK_DATA	; GET THE CLOCK AND DATA LINES
	CALL	C8042			;
	CALL	OBF_42			; WAIT FOR OUTPUT BUFFER FULL
	IN	AL,PORT_A		; GET THE RESULTS
	TEST	AL,KYBD_CLK		; KEYBOARD CLOCK MUST BE LOW
	JZ	G11
	OR	MFG_ERR_FLAG+1,KYCLK_FAIL ; <><><><><><><><><><><><><><>
					; <><> KEYBOARD CLOCK HIGH<><><>
	MOV	SI,OFFSET F1_B		; DISPLAY 304 ERROR
	JMP	F6D			; REPORT ERROR
G11:	CALL	KBD_RESET		; ISSUE RESET TO KEYBRD
	JCXZ	F6			; PRINT ERR MSG IF NO INTERRUPT
	MOV	AL,37H			;<><><><><><><><><><><><><><>
	OUT	MFG_PORT,AL		;<><><>CHECKPOINT 37 <><><><>
	CMP	BL,0AAH 		; SCAN CODE AS EXPECTED?
	JNE	F6			; NO - DISPLAY ERROR MSG

;----- CHECK FOR STUCK KEYS

	MOV	AL,38H			;<><><><><><><><><><><><><><>
	OUT	MFG_PORT,AL		;<><><>CHECKPOINT 38 <><><><>

	MOV	AL,ENA_KBD		; ASSURE KEYBOARD ENABLED
	CALL	C8042			; ISSUE THE COMMAND
	SUB	CX,CX
F5:	LOOP	F5			; DELAY FOR A WHILE
	IN	AL,STATUS_PORT		; CHECK FOR STUCK KEYS
	TEST	AL,OUT_BUF_FULL 	; OUT BUFFER FULL?
	JE	F7			; YES - CONTINUE TESTING

	MOV	AL,39H			;<><><><><><><><><><><><><><>
	OUT	MFG_PORT,AL		;<><><>CHECKPOINT 39 <><><><>

	IN	AL,PORT_A		; GET THE SCAN CODE
	CALL	XPC_BYTE		; CONVERT AND PRINT
	JMP	F6C			; CONTINUE

;------- KEYBOARD ERROR TRY TO DETERMINE IF 8042 INTERFACE IS WORKING

F6:	CLI				;
	MOV	AL,INTR_FACE_CK 	; COMMAND TO 8042
	OUT	STATUS_PORT,AL		;
	SUB	CX,CX			;
	MOV	BH,05			; WAIT FOR OUTPUT BUFFER FULL
F6A:	IN	AL,STATUS_PORT		;
	TEST	AL,OUT_BUF_FULL 	; 8042 FINISHED TEST?
	LOOPZ	F6A			;
	JNZ	F6B			; GO CHECK RESULTS
	DEC	BH			;
	JNZ	F6A			; TRY AGAIN
	MOV	SI,OFFSET F1_A		; INDICATE PLANAR FAILURE
	JMP	F6D			;    (REMOVE KEYBOARD TRY AGAIN)
F6B:	IN	AL,PORT_A		; GET THE RESULTS OF INTERFACE TEST
	CMP	AL,0			; IS THE INTERFACE OK?
	JZ	F6C			;
	OR	MFG_ERR_FLAG+1,KY_SYS_FAIL;<><><><><><><><><><><><><><>
					;<><> KEYBOARD/SYSTEM<><><><><>
	MOV	SI,OFFSET F1_A		; PLANAR FAILURE
	JMP	F6D			; GO IF YES
F6C:	MOV	SI,OFFSET F1		; GET MSG ADDRESS

	OR	MFG_ERR_FLAG+1,KYBD_FAIL;<><><><><><><><><><><><><><><>
					;<><> KEYBOARD FAILED<><><><><>

F6D:	CALL	E_MSG			; PRINT MSG ON SCREEN

;------- INITIALIZE 8042 TO HONOR KEY LOCK

F7:	MOV	AL,3AH			;<><><><><><><><><><><><><><>
	OUT	MFG_PORT,AL		;<><><>CHECKPOINT 3A <><><><>

	MOV	AL,0FFH 		; DISABLE INTERRUPTS
	OUT	INTA01,AL		;
	CLI
	MOV	AL,60H			; WRITE 8042 RAM COMMAND
	CALL	C8042			; ISSUE THE COMMAND
	MOV	AL,45H			; SET SYSTEM FLAG - OUTBUF INT -
	OUT	PORT_A,AL		; SYSTEM FLAG - PC 1 COMPATIBILITY
					; RESET INHIBIT OVER RIDE
;------- DEGATE ADDRESS LINE 20

	MOV	AH,DISABLE_BIT20	; SET COMMAND IN AH
	CALL	GATE_A20		; ISSUE THE COMMAND

;------- SETUP HARDWARE INT VECTOR TABLE LVL 0-7

	SUB	AX,AX			;
	MOV	ES,AX
	MOV	CX,08			; GET VECTOR CNT
	PUSH	CS			; SETUP DS SEG REG
	POP	DS
	MOV	SI,OFFSET VECTOR_TABLE
	MOV	DI,OFFSET INT_PTR
F7A:	MOVSW
	INC	DI			; SKIP OVER SEGMENT
	INC	DI
	LOOP	F7A

;------- SETUP HARDWARE INT VECTOR TABLE LVL 8-15 (VECTORS START AT INT 70H)

	SUB	AX,AX			;
	MOV	ES,AX
	MOV	CX,08			; GET VECTOR COUNT
	PUSH	CS			; SETUP DS SEG REG
	POP	DS
	MOV	SI,OFFSET SLAVE_VECTOR_TABLE
	MOV	DI,OFFSET SLAVE_INT_PTR
F7A1:	MOVSW
	INC	DI			; SKIP OVER SEGMENT
	INC	DI
	LOOP	F7A1

;----- SET UP OTHER INTERRUPTS AS NECESSARY

	ASSUME	DS:ABS0
	SUB	AX,AX				; DS=0
	MOV	DS,AX
	MOV	NMI_PTR,OFFSET NMI_INT		; NMI INTERRUPT
	MOV	INT5_PTR,OFFSET PRINT_SCREEN	; PRINT SCREEN
	MOV	BASIC_PTR+2,0F600H		; SEGMENT FOR CASSETTE BASIC

;-------- ZERO RESERVED VECTORS

	MOV	DI,60H*4			; INT 60 THRU 67 FILL WITH ZERO
	MOV	CX,14				; CLEAR 14 WORDS
F7A2:	MOV	WORD PTR DS:[DI],0
	ADD	DI,2				; POINT TO NEXT LOCATION
	LOOP	F7A2				;

;----- SETUP TIMER 0 TO BLINK LED IF MANUFACTURING TEST MODE

	TEST	DATA_AREA[MFG_TST-DATA_BASE],LOOP_POST ; MFG. TEST MODE?
	JNZ	F9
	MOV	INT_ADDR,OFFSET BLINK_INT	; SETUP TIMER TO BLINK LED
	MOV	AL,0FEH 			; ENABLE TIMER INTERRUPT
	OUT	INTA01,AL
F9:	STI					; ALLOW INTERRUPTS

	ASSUME	DS:DATA
	CALL	DDS			; ESTABLISH DATA SEGMENT
					;   THE OPERATING SYSTEM

;-------- ISSUE A RESET TO THE HARD FILE IF SOFT RESET

	CMP	RESET_FLAG,1234H	; SOFT RESET?
	JNZ	F9A			; CONTINUE IF NOT
	MOV	CX,0FFH 		;
	MOV	DX,03F6H		;
	MOV	AL,04H			; RESET
	OUT	DX,AL			;
F9_A:	LOOP	F9_A			; HOLD RESET
	SUB	AL,AL			;
	OUT	DX,AL			; REMOVE RESET

;----------------------------------------------------------------
; TEST.23							:
;	DISKETTE ATTACHMENT TEST				:
; DESCRIPTION							:
;	CHECK IF IPL DISKETTE DRIVE IS ATTACHED TO SYSTEM.  IF	:
;	ATTACHED, VERIFY STATUS OF NEC FDC AFTER A RESET. ISSUE :
;	A RECAL AND SEEK CMD TO FDC AND CHECK STATUS. COMPLETE	:
;	SYSTEM INITIALIZATION THEN PASS CONTROL TO THE BOOT	:
;	LOADER PROGRAM. 					:
;----------------------------------------------------------------

F9A:	MOV	AL,3CH			;<><><><><><><><><><><><><><>
	OUT	MFG_PORT,AL		;<><><>CHECKPOINT 3C <><><><>

	MOV	AL,02H			; SET DATA RATE TO 250 K BITS / SEC
	MOV	DX,3F7H 		;
	OUT	DX,AL			;
	TEST	BYTE PTR EQUIP_FLAG,01H  ; DISKETTE PRESENT?
	JZ	F15
	TEST	MFG_TST,LOOP_POST	; MFG JUMPER INSTALLED?
	JZ	F15			; GO IF YES
F10:					; DISK_TEST:
	IN	AL,INTA01
	JMP	SHORT $+2		; IO DELAY
	AND	AL,0BFH 		; ENABLE DISKETTE INTERRUPTS
	OUT	INTA01,AL
	MOV	AH,0			; RESET NEC FDC
	MOV	DL,AH			; SET FOR DRIVE 0
	INT	13H			; VERIFY STATUS AFTER RESET
	TEST	AH,0FFH 		; STATUS OK?
	JNZ	F13			; NO - FDC FAILED

;----- TURN DRIVE 0 MOTOR ON

	MOV	DX,03F2H		; GET ADDR OF FDC CARD
	MOV	AL,1CH			; TURN MOTOR ON, EN DMA/INT
	OUT	DX,AL			; WRITE FDC CONTROL REG
	SUB	CX,CX
	MOV	DL,12			; WAIT 1 SECOND
F11:					; MOTOR_WAIT:
	LOOP	F11			; WAIT 1 SECOND
	DEC	DL			; DECREMENT OUTER LOOP
	JNZ	F11			;

	XOR	DX,DX			; SELECT DRIVE 0
	MOV	CH,1			; SELECT TRACK 1
	MOV	SEEK_STATUS,DL
	CALL	SEEK			; RECALIBRATE DISKETTE
	JC	F13			; GO TO ERR SUBROUTINE IF ERR
	MOV	CH,34			; SELECT TRACK 34
	CALL	SEEK			; SEEK TO TRACK 34
	JNC	F14			; OK, TURN MOTOR OFF
F13:					; DSK_ERR:

	OR	MFG_ERR_FLAG+1,DSK_FAIL ;<><><><><><><><><><><><><><><>
					;<><> DISKETTE FAILED<><><><><>
	MOV	SI,OFFSET F3		; GET ADDR OF MSG
	CALL	E_MSG			; GO PRINT ERROR MSG

;----- TURN DRIVE 0 MOTOR OFF

F14:					; DR0_OFF:
	MOV	AL,0CH			; TURN DRIVE 0 MOTOR OFF
	MOV	DX,03F2H		; FDC CTL ADDRESS
	OUT	DX,AL

;------ SETUP KEYBOARD PARAMETERS

F15:	MOV	INTR_FLAG,00H		; SET STRAY INTERRUPT FLAG = 00
	MOV	SI,OFFSET KB_BUFFER	; SETUP KEYBOARD PARAMETERS
	MOV	BUFFER_HEAD,SI
	MOV	BUFFER_TAIL,SI
	MOV	BUFFER_START,SI
	ADD	SI,32			;DEFAULT BUFFER OF 32 BYTES
	MOV	BUFFER_END,SI

;-------- SET PRINTER TIMEOUT DEFAULT

	MOV	DI,OFFSET PRINT_TIM_OUT ;SET DEFAULT PRINTER TIMEOUT
	PUSH	DS
	POP	ES
	MOV	AX,1414H		; DEFAULT=20
	STOSW
	STOSW

;-------- SET RS232 DEFAULT

	MOV	AX,0101H		;RS232 DEFAULT=01
	STOSW
	STOSW

;-------- ENABLE TIMER INTERRUPTS

	IN	AL,INTA01
	AND	AL,0FEH 		; ENABLE TIMER AND KB INTS
	JMP	SHORT $+2		; IO DELAY
	OUT	INTA01,AL

;------- CHECK CMOS BATTERY/CHECKSUM

	TEST	MFG_TST,LOOP_POST	; MFG JUMPER?
	JNZ	B1_OK			; GO IF NOT
	JMP	F15C			; BYPASS IF YES
B1_OK:	MOV	AL,DIAG_STATUS		;
	OUT	CMOS_PORT,AL		;
	JMP	SHORT $+2		; IO DELAY
	IN	AL,CMOS_PORT+1		;
	AND	AL,0E0H 		; BAD BATTERY, CHK SUM, OR MIN CONFIG?
	JZ	C_OK			; GO IF NOT
	TEST	AL,80H			; BATTERY BAD?
	MOV	SI,OFFSET CM1		; PRELOAD BATTERY MSG
	JZ	B2_OK			; GO IF BATTERY OK
	CALL	E_MSG			; PRINT BATTERY MSG
	JMP	H_OK1A			; CONTINUE(BYPASS CLOCK ETC)
B2_OK:
	MOV	SI,OFFSET CM2		; PRE LOAD CKSUM BAD
	CALL	E_MSG			; PRINT MSG
	JMP	H_OK1A			; BYPASS CLOCK TEST-MEM SIZE

;------- TEST CLOCK UPDATING

C_OK:	MOV	BL,03H			; OUTER LOOP COUNT
D_OK:	SUB	CX,CX			; INNER LOOP COUNT
E_OK:	MOV	AL,CLK_UP		; GET THE CLOCK UPDATE BYTE
	OUT	CMOS_PORT,AL		;
	JMP	SHORT $+2		; IO DELAY
	IN	AL,CMOS_PORT+1		;
	TEST	AL,80H			; CHECK FOR UPDATE IN PROGRESS
	JNZ	G_OK			; GO IF YES
	LOOP	E_OK			; TRY AGAIN
	DEC	BL			; DEC OUTER LOOP
	JNZ	D_OK			; TRY AGAIN
F_OK:	MOV	SI,OFFSET CM3		; PRINT MSG
	CALL	E_MSG			;

;------- SET CMOS DIAG_STATUS 04 (CLOCK ERROR)

	MOV	AL,DIAG_STATUS		; SET CLOCK ERROR
	OUT	CMOS_PORT,AL		;
	XCHG	AL,AH			; SAVE STATUS ADDRESS
	JMP	SHORT $+2		; IO DELAY
	IN	AL,CMOS_PORT+1		; GET THE CURRENT STATUS
	OR	AL,CMOS_CLK_FAIL	; SET NEW STATUS
	XCHG	AL,AH			; GET STATUS ADDR AND SAVE NEW STATUS
	OUT	CMOS_PORT,AL		;
	XCHG	AL,AH			;
	JMP	SHORT $+2		; IO DELAY
	OUT	CMOS_PORT+1,AL		;
	JMP	H_OK			; CONTINUE

;-------- CHECK CLOCK UPDATE

G_OK:	MOV	CX,600			; LOOP COUNT
I_OK:	MOV	AL,CLK_UP		; CHECK FOR OPPOSITE STATE
	OUT	CMOS_PORT,AL		;
	JMP	SHORT $+2		; IO DELAY
	IN	AL,CMOS_PORT+1		;
	TEST	AL,80H			;
	LOOPNZ	I_OK			; TRY AGAIN
	JCXZ	F_OK			; PRINT ERROR IF TIMEOUT

;-------- CHECK MEMORY SIZE DETERMINED = CONFIG

H_OK:
	MOV	AL,DIAG_STATUS		; GET THE STATUS BYTE
	OUT	CMOS_PORT,AL		;
	JMP	SHORT $+2		; IO DELAY
	IN	AL,CMOS_PORT+1		;
	TEST	AL,W_MEM_SIZE		; WAS THE CONFIG=MEM_SIZE_DETERMINED?
	JZ	H_OK1A			; GO IF YES

;-------- MEMORY SIZE ERROR

	MOV	SI,OFFSET E1_A		; PRINT SIZE ERROR
	CALL	E_MSG			; DISPLAY ERROR

;-------- CHECK FOR CRT ERROR

H_OK1A: CMP	MFG_ERR_FLAG,0CH	; CHECK FOR MONO CRT ERROR
	MOV	SI,OFFSET E1_B		; PRELOAD MONO CRT ERROR
	JZ	H_OK1B			; GO IF YES

	CMP	MFG_ERR_FLAG,0DH	; CHECK FOR COLOR CRT ERROR
	JNZ	J_OK			; CONTINUE IF NOT
	MOV	SI,OFFSET E1_C		; CRT ERROR MSG
H_OK1B: CALL	E_MSG			;


	;=======================================
;------- CHECK FOR COMBO HARD FILE/DISKETTE CARD
	;=======================================
J_OK:
	MOV	BL,0FH			; OUTER LOOP COUNT WAIT FOR BUSY OFF
	SUB	CX,CX			;
	MOV	DX,01F7H		; HARD FILE STATUS PORT
J_OK1:	IN	AL,DX			; GET THE STATUS
	TEST	AL,080H 		; IS THE CONTROLLER BUSY?
	JZ	J_OK2			; CONTINUE IF NOT
	LOOP	J_OK1			; TRY AGAIN
	DEC	BL			; DECREMENT OUTER LOOP
	JNZ	J_OK1			; TRY AGAIN IF NOT ZERO
	AND	AL,0CH			; BITS 2 & 3 = 0 IF COMBO CARD
	JZ	J_OK3			; GO IF YES
	JMP	F15C			; NO COMBO CARD

J_OK2:	MOV	DX,1F4H 		; VERIFY COMBO CARD
	MOV	AL,055H 		;  WRITE TO THE CYL BYTE
	OUT	DX,AL			;
	JMP	SHORT $+2		; IO DELAY
	IN	AL,DX			; CHECK DATA WRITTEN = DATA READ
	CMP	AL,055H 		;
	JNZ	F15C			; GO IF NOT
	MOV	AL,0AAH 		; WRITE ANOTHER PATTERN
	OUT	DX,AL			;
	JMP	SHORT $+2		; IO DELAY
	IN	AL,DX			;
	CMP	AL,0AAH 		; IS DATA PATTERN THE SAME?
	JNZ	F15C			; GO IF NOT

J_OK3:	MOV	HF_CNTRL,DUAL		; SET THE HF/FLOPPY SWITCH ON

;------- INITIALIZE FLOPPY FOR DRIVE TYPE

	MOV	AL,3DH			;<><><><><><><><><><><><><><><>
	OUT	MFG_PORT,AL		;<><><>CHECKPOINT 3D <><><><><>
	CALL	DSKETTE_SETUP		; INITIALIZE FLOPPY

;-------- CHECK FOR 2ND DISKETTE DRIVE
	CALL	DDS			; INSURE DATA SEGMENT
	CMP	DSK_STATE+1,0		; IS THERE A DRIVE 2 ATTACHED?
	JZ	F15C			; GO IF NOT
	OR	BYTE PTR EQUIP_FLAG,40H ; SET SECOND DRIVE INSTALLED

;------- INITIALIZE HARD FILE

F15C:	MOV	AL,3EH			;<><><><><><><><><><><><><><><>
	OUT	MFG_PORT,AL		;<><><>CHECKPOINT 3E <><><><><>

	MOV	AL,DIAG_STATUS		; GET THE CMOS STATUS
	OUT	CMOS_PORT,AL		;
	JMP	SHORT $+2		;
	IN	AL,CMOS_PORT+1		;
	TEST	AL,0C0H 		; BATTERY/CHECKSUM OK
	JNZ	ROM_SCAN1		; BYPASS DISK SETUP IF NOT

	MOV	AL,HD_FILE_TYPE 	; INSURE CMOS DEFINES THE TYPE OF HARD FILE
	OUT	CMOS_PORT,AL		;
	JMP	SHORT $+2		;
	IN	AL,CMOS_PORT+1		;
	CMP	AL,0H			; INSURE TYPE IS DEFINED
	JZ	ROM_SCAN1		; BYPASS DISK SETUP IF NOT

	CALL	DISK_SETUP		; INITIALIZE HARD FILE

;-----------------------------------------------------------
; TEST.22						   :
; CHECK FOR OPTIONAL ROM FROM C800->E000 IN 2K BLOCKS	   :
;	(A VALID MODULE HAS '55AA' IN THE FIRST 2 LOCATIONS:
;	LENGTH INDICATOR (LENGTH/512) IN THE 3RD LOCATION  :
;	AND TEST/INIT. CODE STARTING IN THE 4TH LOCATION)  :
;-----------------------------------------------------------
ROM_SCAN1:
	STI					; ALLOW INTERRUPTS
	MOV	AL,3BH				;<><><><><><><><><><><><><><>
	OUT	MFG_PORT,AL			;<><><>CHECKPOINT 3B <><><><>
	CALL	DDS				; SET REAL MODE DATA SEGMENT
	MOV	AL,10				; LINE FEED ON CRT
	CALL	PRT_HEX
ROM_SCAN:

;------- SET DMA MASK AND REQUEST REGISTERS

	SUB	AL,AL			;
	OUT	DMA18+2,AL		; SEND ZERO TO MASK REG
	JMP	SHORT $+2		;
	OUT	DMA18+4,AL		; SEND ZERO TO REQ REG
	MOV	DX,0C800H		; SET BEGINNING ADDRESS
ROM_SCAN2:
	MOV	DS,DX
	SUB	BX,BX			; SET BX=0000
	MOV	AX,[BX] 		; GET 1ST WORD FROM MODULE
	PUSH	BX
	POP	BX			; BUS SETTLING
	CMP	AX,0AA55H		; = TO ID WORD?
	JNZ	NEXT_ROM		; PROCEED TO NEXT ROM IF NOT
	CALL	ROM_CHECK		; GO CHECK OUT MODULE
	JMP	ARE_WE_DONE		; CHECK FOR END OF ROM SPACE
NEXT_ROM:
	ADD	DX,0080H		; POINT TO NEXT 2K ADDRESS
ARE_WE_DONE:
	CMP	DX,0E000H		; AT E0000 YET?
	JL	ROM_SCAN2		; GO CHECK ANOTHER ADD. IF NOT

;-------- TEST FOR KEYBOARD LOCKED

	CALL	DDS			; SET DATA SEGMENT
	IN	AL,STATUS_PORT		; IS KEYBOARD UNLOCKED?
	AND	AL,KYBD_INH		;
	JZ	KEY1
	JMP	KEY10			; GO IF OFF
KEY1:
	OR	MFG_ERR_FLAG+1,KEY_FAIL ;<><><><><><><><><><><><><><><>
					;<><> KEYBOARD IS LOCKED <><><>

KEY9:
	ASSUME	DS:DATA

	MOV	SI,OFFSET LOCK		; PRINT LOCKED MESSAGE	(302)
	CALL	E_MSG			;

KEY10:
	;====================
;-------- SETUP PRINTER_BASE
	;====================

	MOV	DI,OFFSET F4		; PRT_SRC_TBL
	MOV	SI,0
F16:					; PRT_BASE:
	MOV	DX,CS:[DI]		; GET PRINTER BASE ADDR
	MOV	AL,0AAH 		; WRITE DATA TO PORT A
	OUT	DX,AL
	JMP	SHORT $+2		; IO DELAY
	PUSH	DS			; BUS SETTLING
	IN	AL,DX			; READ PORT A
	POP	DS
	CMP	AL,0AAH 		; DATA PATTERN SAME
	JNE	F17			; NO - CHECK NEXT PRT CD
	MOV	PRINTER_BASE[SI],DX	; YES - STORE PRT BASE ADDR
	INC	SI			; INCREMENT TO NEXT WORD
	INC	SI
F17:
	INC	DI			; POINT TO NEXT BASE ADDR
	INC	DI
	CMP	DI,OFFSET F4E		; ALL POSSIBLE ADDRS CHECKED?
	JNE	F16			; PRT_BASE
	;=============
;------- SETUP RS232
	;=============
	MOV	BX,0			; POINTER TO RS232 TABLE
	MOV	DX,3FAH 		; CHECK IF RS232 CD 1 ATTCH?
	IN	AL,DX			; READ INTR ID REG
	TEST	AL,0F8H
	JNZ	F18
	MOV	RS232_BASE[BX],3F8H	; SETUP RS232 CD #1 ADDR
	INC	BX
	INC	BX
F18:	MOV	DX,2FAH 		; CHECK IF RS232 CD 2 ATTCH
	IN	AL,DX			; READ INTERRUPT ID REG
	TEST	AL,0F8H
	JNZ	F19			; BASE_END
	MOV	RS232_BASE[BX],2F8H	; SETUP RS232 CD #2
	INC	BX
	INC	BX
       ;===============================================================
;----- SET UP EQUIP_FLAG TO INDICATE NUMBER OF PRINTERS AND RS232 CARDS
       ;===============================================================
F19:					; BASE_END:
	MOV	AX,SI			; SI HAS 2* NUMBER OF RS232
	MOV	CL,3			; SHIFT COUNT
	ROR	AL,CL			; ROTATE RIGHT 3 POSITIONS
	OR	AL,BL			; OR IN THE PRINTER COUNT
	MOV	BYTE PTR EQUIP_FLAG+1,AL	; STORE AS SECOND BYTE

	;=================================
;------- TEST FOR ANY ERRORS (BP NOT ZERO)
	;=================================
K_OK:
;-------- CLEAR KEYBOARD STATE FLAGS

	SUB	AX,AX			; RESET ALL KEYBOARD STATUS FLAGS
	MOV	WORD PTR KB_FLAG,AX

;-------- ENABLE KEYBOARD INTERRUPTS

	IN	AL,INTA01
	AND	AL,0FDH 		; ENABLE TIMER AND KB INTS
	JMP	SHORT $+2		; IO DELAY
	OUT	INTA01,AL

	MOV	BYTE PTR MFG_ERR_FLAG,0 ; CLEAR MFG ERROR FLAG
	CMP	BP,0000H		; CHECK FOR BP= NON-ZERO
					; (ERROR HAPPENED)
	JE	F15A_0			; CONTINUE IF NO ERROR

	CMP	BYTE PTR RESET_FLAG,64H ; MFG RUN IN MODE?
	JNZ	ERR_WAIT		; GO IF NOT

;-------- MFG RUN IN MODE -> SET ERROR FLAG

	MOV	BYTE PTR MFG_ERR_FLAG,0AAH	; INDICATE ERROR
	JMP	F15A_0				; CONTINUE
ERR_WAIT:
	MOV	DX,2			; 2 SHORT BEEPS (ERROR)
	CALL	ERR_BEEP

	IN	AL,STATUS_PORT		; CHECK IF RESUME MSG TO BE DISPLAYED
	AND	AL,KYBD_INH		;
	MOV	SI,OFFSET F3D		; RESUME ERROR MSG
	JNZ	ERR_WAIT2		;
	MOV	SI,OFFSET F3D1		; ERROR MSG FOR KEYBOARD LOCKED
	CALL	P_MSG			;
	MOV	SI,OFFSET F3D		; RESUME MSG
ERR_WAIT2:
	CALL	P_MSG

;-------- INIT PRINTER	(ALT DISPLAY DEVICE)

	MOV	AH,1			;
	SUB	DX,DX			; FIRST PRINTER
	INT	17H			;
ERR_WAIT1:
	MOV	AL,3FH			;<><><><><><><><><><><><><><><>
	OUT	MFG_PORT,AL		;<><><>CHECKPOINT 3F <><><><><>
	MOV	AH,00
	INT	16H			; WAIT FOR 'F1' KEY
	CMP	AH,3BH
	JNE	ERR_WAIT1
F15A_0:
	TEST	MFG_TST,LOOP_POST	; MFG BURN IN MODE
	JNZ	F15A			; GO IF NOT
	JMP	START_1 		; GO LOOP POST
F15A:	CMP	BYTE PTR RESET_FLAG,64H ; MFG RUN IN?
	JZ	F15B			; BYPASS BEEP IF YES

	MOV	DX,1			; 1 SHORT BEEP (NO ERRORS)
	CALL	ERR_BEEP

F15B:	SUB	AH,AH			; CLEAR FLAGS
	MOV	AL,CRT_MODE
	INT	10H			; CLEAR SCREEN

;-------- CLEAR DESCRIPTOR TABLES

F20:	MOV	CX,0500 		; CLEAR 1K
	MOV	DI,SYS_IDT_LOC		; POINT ES TO START OF DESCRIPTORS
	SUB	AX,AX
	MOV	ES,AX			;
F20_A:	MOV	ES:[DI],AX		; CLEAR
	ADD	DI,2			; POINT TO NEXT LOCATION
	LOOP	F20_A			; CONTINUE TILL DONE

	  ;===============
;-------- SET TIME OF DAY
	  ;===============

	CALL	SET_TOD

;-------- SET SYSTEM STACK

	MOV	AX,STACK		; GET THE STACK SEGMENT
	MOV	SS,AX			;
	MOV	SP,OFFSET TOS		;

;------- ENABLE HARDWARE INTERRUPT IF MATH PROCESSOR (X287)


	MOV	AL,40H			;<><><><><><><><><><><><><><><>
	OUT	MFG_PORT,AL		;<><><>CHECKPOINT 40 <><><><><>
	MOV	AX,IO_ROM_INIT		; TEMP STORAGE
	PUSH	AX
	SUB	AX,AX			; CLEAR IO_ROM_INIT
	MOV	IO_ROM_INIT,AX		;
	ESC	28,BX			;
	XOR	AX,AX			;
	ESC	15,IO_ROM_INIT		;
	PUSHA				; TIME FOR 287 TO RESPOND
	POPA				;
	AND	IO_ROM_INIT,01F3FH	; CLEAR UNUSED 287 BITS
	CMP	IO_ROM_INIT,0033FH	; IS THE 287 INSTALLED?
	JNZ	NO_287			; GO IF MATH PROCESSOR IS NOT INSTALLED

	WAIT
	ESC	02FH,IO_ROM_INIT	; STORE THE STATUS WORD
	PUSHA				; TIME FOR 287 TO RESPOND
	POPA
	TEST	IO_ROM_INIT,0B8BFH	; ALL BITS SHOULD BE OFF
	JNZ	NO_287			; GO IF NOT INSTALLED

	IN	AL,INTB01		; GET THE SLAVE INT MASK
	AND	AL,0DFH 		; ENABLE 287 INTERRUPTS
	JMP	SHORT $+2		; IO DELAY
	OUT	INTB01,AL

;-------- ENSURE THAT MASTER LEVEL 2 ENABLED

	IN	AL,INTA01		; GET THE CURRENT MASK
	AND	AL,0FBH 		;
	JMP	SHORT $+2		; IO DELAY
	OUT	INTA01,AL		;
	OR	BYTE PTR EQUIP_FLAG,02H ; SET 287 BIT ON
NO_287:

	POP	AX			; RESTORE IO_ROM_INIT
	MOV	IO_ROM_INIT,AX		;

;--------- TEST FOR MFG RUN-IN TEST

	CMP	BYTE PTR RESET_FLAG,64H ; IS THE THE MFG RUN-IN TEST?
	JNZ	END_287 		; GO IF NOT
	JMP	SHUT4			; BOOT LOAD IF YES

;-------- UNMASK SLAVE HARDWARE INT 9 (LEVEL 71)
END_287:
	IN	AL,INTB01		; GET THE CURRENT MASK
	AND	AL,0FDH 		;
	JMP	SHORT $+2		; IO DELAY
	OUT	INTB01,AL		; SET NEW MASK

;------------------------------------------------------------------
; TEST FOR SYSTEM CODE AT SEGMENT E000:0
;   FIRST WORD = AA55H
;   LAST BYTE = CHECKSUM
;   ENTRY POINT = FIRST BYTE + 3
; IF TEST IS SUCCESSFUL A CALL FAR TO THE ENTRY POINT IS EXECUTED
;------------------------------------------------------------------
	MOV	AL,41H			;<><><><><><><><><><><><><><><>
	OUT	MFG_PORT,AL		;<><><>CHECKPOINT 41 <><><><><>

	MOV	AL,CMOS_END		; INSURE NMI OFF
	OUT	CMOS_PORT,AL

;ENDIF

	MOV	BYTE PTR RESET_FLAG,0	; CLEAR FLAG
	MOV	AX,0E000H		; SEGMENT OF SYSTEM CODE
	MOV	ES,AX			;
	SUB	DI,DI
	MOV	AX,ES:[DI]		; CHECK FOR AA55
	PUSH	BX			; BUS SETTLE
	POP	BX
	CMP	AX,0AA55H		;
	PUSHF				; SAVE FLAGS
	MOV	ES:[DI],AX		; CLEAR POSSIBLE PARITY CHECK
	IN	AL,PORT_B		;
	OR	AL,RAM_PAR_OFF		; TOGGLE IO/PAR CHECK ENABLE
	JMP	SHORT $+2		; IO DELAY
	OUT	PORT_B,AL		;
	AND	AL,RAM_PAR_ON		;
	JMP	SHORT $+2		; IO DELAY
	OUT	PORT_B,AL		;
	POPF				; RESTORE FLAGS
	JNZ	SHUT4			; CONTINUE

;------- CHECKSUM SYSTEM CODE

	PUSH	DS
	PUSH	ES			; SET SEGMENT TO TEST
	POP	DS			;
	SUB	BX,BX			; STARTING OFFSET
	CALL	ROS_CHECKSUM		;
	POP	DS			; RESTORE DATA SEGMENT
	JNZ	SHUT4			; GO IF CHECKSUM NOT OK

;-------- ENABLE NMI AND IO/PAR CHECKS

	MOV	AL,2DH			; ENABLE NMI
	OUT	CMOS_PORT,AL		;

	IN	AL,PORT_B		; ENABLE PARITY
	JMP	SHORT $+2		; IO DELAY
	AND	AL,RAM_PAR_ON		; ENABLE RAM PCK AND IO CH
	OUT	PORT_B,AL

	MOV	DS:IO_ROM_INIT,0003H	; SET THE OFFSET
	MOV	DS:IO_ROM_SEG,ES	; SET THE SEGMENT

	MOV	AL,42H			;<><><><><><><><><><><><><><>
	OUT	MFG_PORT,AL		;<><><>CHECKPOINT 42 <><><><>

;-------- EXIT TO SYSTEM CODE

	CALL	DWORD PTR DS:IO_ROM_INIT	; GO TO SYSTEM CODE
						; VIA CALL

;----- ENABLE NMI INTERRUPTS + ENTRY FROM SHUTDOWN WITH BOOT REQUEST

SHUT4:	MOV	AL,2DH			; ENABLE NMI
	OUT	CMOS_PORT,AL		;

	IN	AL,PORT_B		; ENABLE PARITY
	JMP	SHORT $+2		; IO DELAY
	AND	AL,RAM_PAR_ON		; ENABLE RAM PCK AND IO CH
	OUT	PORT_B,AL

	MOV	AL,43H			;<><><><><><><><><><><><><><>
	OUT	MFG_PORT,AL		;<><><>CHECKPOINT 43 <><><><>

	INT	19H			; GO TO BOOT LOADER

POST2	  ENDP
CODE	  ENDS
	  END
